/*
 * @Author: your name
 * @Date: 2021-07-04 16:06:47
 * @LastEditTime: 2021-08-29 01:00:36
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \server\tcp_swarm_libevent.cpp
 */
#define _WSPIAPI_H_
#define _WINSOCKAPI_
#include"tcp_swarm_libevent.h"
#include <cstring>
void conn_writecb(struct bufferevent *, void *);
void conn_readcb(struct bufferevent *, void *);
void conn_eventcb(struct bufferevent *, short, void *);

void conn_writecb(struct bufferevent *bev, void *user_data)
{
}
// 运行线程
int thread_dispatch(TcpSwarmClientLibevent *p) {
    if (nullptr != p) {
        int ret =  event_base_dispatch(p->m_base);;
        return ret;
    }
    return -1;
}

void conn_readcb(struct bufferevent *bev, void *user_data)
{
    TcpSwarmClientLibevent *server = (TcpSwarmClientLibevent*)user_data;
    struct evbuffer *input = bufferevent_get_input(bev);
    size_t sz = evbuffer_get_length(input);
    if (sz > 0)
    {
        uint8_t *msg = new uint8_t[sz];
        int ret = bufferevent_read(bev,msg,sz);
        printf("%s\n", msg);
        delete[] msg;
    }
}

void conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
    TcpSwarmClientLibevent *server;
    server = (TcpSwarmClientLibevent *)user_data;
    if (events & BEV_EVENT_EOF)
    {
        evutil_socket_t fd = bufferevent_getfd(bev);
        bufferevent_free(bev);
        server->removeConection(fd);
    }
    else if (events & BEV_EVENT_ERROR)
    {
        
    }
    else if (events & BEV_EVENT_CONNECTED)
    {
        evutil_socket_t fd = bufferevent_getfd(bev);
        server->addConection(fd,bev);
        std::cout << "conect new fd " << fd << std::endl;
        bufferevent_write(bev, string("hello world").c_str(), strlen("hello world"));
    }
}

TcpSwarmClientLibevent::TcpSwarmClientLibevent(int count){
    m_count = count;
}

int TcpSwarmClientLibevent::addConection(evutil_socket_t fd,struct bufferevent* bev) {
    if(nullptr != bev)
        m_clients[fd] = bev;
    return 0;
}


int TcpSwarmClientLibevent::removeConection(evutil_socket_t fd){
    m_clients.erase(fd);
    return 0;
}

int TcpSwarmClientLibevent::ConnectToServer(string server, int port){
    memset(&m_addr, 0, sizeof(m_addr));
#ifdef linux
    m_addr.sin_addr.s_addr = inet_addr(server.c_str());
    m_addr.sin_family = AF_INET;
#endif
#ifdef _WIN32
    m_addr.sin_addr.S_un.S_addr = inet_addr(server.c_str());
    m_addr.sin_family = AF_INET;
#endif
    m_addr.sin_port = htons(port);
    m_base = event_base_new();
    if (!m_base){
        printf("Could not initialize libevent\n");
        return -1;
    }
#ifdef WIN32
        evthread_use_windows_threads();
#else
        evthread_use_pthreads();
#endif
    evthread_make_base_notifiable(m_base);
    for(uint32_t i = 0; i < this->m_count;i++){
        m_bev = bufferevent_socket_new(m_base, -1,
                                    BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
        if (nullptr == m_bev) {
            return - 1;
        }
        bufferevent_setcb(m_bev, conn_readcb, conn_writecb, conn_eventcb, this);
        int flag = bufferevent_socket_connect(m_bev, (struct sockaddr *)&m_addr, sizeof(m_addr));
        bufferevent_enable(m_bev, EV_READ | EV_WRITE);
        if (-1 == flag)
        {
            printf("Connect failed\n");
            bufferevent_free(m_bev);
            m_bev = nullptr;
            return -1;
        }
    }
    this->m_thread = new thread(thread_dispatch,this);
    return 0;
}

